#include <QAbstractItemView>
#include <QMouseEvent>
#include <QScrollBar>
#include <QApplication>
#include <QDebug>
#include <QtGlobal>
#include "comboboxex.h"

ComboBoxEx::ComboBoxEx(QWidget *parent) :
    QComboBox(parent), m_MousePressed(false), m_TotalMove(0), m_ScrollPosOnPress(0)
{
    view()->viewport()->installEventFilter(this);
}

bool ComboBoxEx::eventFilter(QObject *target, QEvent *event)
{
    if(target == view()->viewport())
    {
        if(event->type() == QEvent::MouseButtonPress) {
            qDebug() << "viewport QEvent::MouseButtonPress";
            viewOnMousePress(static_cast<QMouseEvent *>(event));
            return true;
        } else if(event->type() == QEvent::MouseButtonRelease) {
            qDebug() << "viewport QEvent::MouseButtonRelease";
            viewOnMouseRelease(static_cast<QMouseEvent *>(event));
            return true;
        } else if(event->type() == QEvent::MouseMove) {
            qDebug() << "viewport QEvent::MouseMove";
            viewOnMouseMove(static_cast<QMouseEvent *>(event));
            return true;
        }
    }

    // 交给基类处理
    return QComboBox::eventFilter(target, event);
}

void ComboBoxEx::viewOnMouseMove(QMouseEvent *e)
{
    qDebug() << "ComboBoxEx::viewOnMouseMove " << e->pos();

    if (!m_MousePressed)
    {
        return;
    }

    QPoint currentPt = e->pos();
    int dist = m_PressPosition.y() - currentPt.y();
    int deltaValue = dist / view()->sizeHintForRow(0);
    view()->verticalScrollBar()->setValue(m_ScrollPosOnPress + deltaValue);
    m_TotalMove += qAbs(dist);
}

void ComboBoxEx::viewOnMousePress(QMouseEvent *e)
{
    qDebug() << "ComboBoxEx::viewOnMousePress";

    m_MousePressed = true;
    m_TotalMove = 0;
    m_ScrollPosOnPress = view()->verticalScrollBar()->value();
    m_PressPosition = e->pos();
}

void ComboBoxEx::viewOnMouseRelease(QMouseEvent *e)
{
    qDebug() << "ComboBoxEx::viewOnMouseRelease";

    Q_UNUSED(e);
    m_MousePressed = false;

    // 移动距离很小，模拟鼠标点击，选择当前项
    if(qAbs(m_TotalMove) <= 2) {
        view()->viewport()->removeEventFilter(this);
        QMouseEvent mp(QEvent::MouseButtonPress, e->pos(), Qt::LeftButton, Qt::LeftButton, 0);
        QMouseEvent mr(QEvent::MouseButtonRelease, e->pos(), Qt::LeftButton, Qt::LeftButton, 0);
        QApplication::sendEvent(view()->viewport(), &mp);
        QApplication::sendEvent(view()->viewport(), &mr);

        view()->viewport()->installEventFilter(this);
    }
}
